﻿using System;
using System.Linq;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Utils.Extends
{
    public static class ComponentExtends
    {
        /// <summary>
        /// 在子物体中按名称查找组件
        /// </summary>
        /// <typeparam name="T">组件类型</typeparam>
        /// <param name="original">父组件</param>
        /// <param name="name">目标物体名称</param>
        /// <param name="includeInactive"> </param>
        /// <returns>找到的组件，未找到则返回null</returns>
        public static T QueryComponent<T>(this Component original, string name, bool includeInactive = true) where T : Component
        {
            if (original == null)
                throw new System.ArgumentNullException(nameof(original));
            if (string.IsNullOrEmpty(name))
                throw new System.ArgumentException("名字不能为空...", nameof(name));
            T[] components = original.GetComponentsInChildren<T>(includeInactive);
            return components.FirstOrDefault(c => c.name.Trim().Equals(name));
        }

        public static Component QueryComponent(this Component original, Type type, string name, bool includeInactive = true)
        {
            if (original == null)
                throw new System.ArgumentNullException(nameof(original));
            if (type == null)
                throw new System.ArgumentNullException(nameof(type));

            if (!typeof(Component).IsAssignableFrom(type))
                throw new ArgumentException($"类型 {type.Name} 必须继承自 Component", nameof(type));
            if (string.IsNullOrEmpty(name))
                throw new System.ArgumentException("名字不能为空...", nameof(name));
            Component[] components = original.GetComponentsInChildren(type, includeInactive);
            return components.FirstOrDefault(c => c.name.Trim().Equals(name));
        }

        public static T GetOrAddComponent<T>(this Component original) where T : Component
        {
            T comp = original.GetComponent<T>();
            if (comp == null)
                comp = original.gameObject.AddComponent<T>();
            return comp;
        }


        /// <summary>
        /// 生成组件的实例
        /// </summary>
        /// <typeparam name="T">组件类型</typeparam>
        /// <param name="original">原始组件</param>
        /// <param name="parent">父物体</param>
        /// <param name="worldPositionStays">是否保持世界坐标</param>
        /// <returns>实例化后的组件</returns>
        public static T CreateInstance<T>(this T original, Transform parent = null, bool worldPositionStays = false) where T : Component
        {
            if (original == null)
                throw new System.ArgumentNullException(nameof(original));
            return Object.Instantiate(original, parent, worldPositionStays);
        }

        /// <summary>
        /// 生成组件的实例（带位置和旋转）
        /// </summary>
        /// <typeparam name="T">组件类型</typeparam>
        /// <param name="original">原始组件</param>
        /// <param name="position">位置</param>
        /// <param name="rotation">旋转</param>
        /// <param name="parent">父物体</param>
        /// <returns>实例化后的组件</returns>
        public static T CreateInstance<T>(this T original, Vector3 position, Quaternion rotation, Transform parent = null) where T : Component
        {
            if (original == null)
                throw new System.ArgumentNullException(nameof(original));
            return Object.Instantiate(original, position, rotation, parent);
        }

        /// <summary>
        /// 销毁组件
        /// </summary>
        /// <param name="original">原始组件</param>
        /// <param name="immediately">马上的</param>
        public static void Destroy(this Component original, bool immediately = false)
        {
            if (original == null)
                return;
            if (immediately)
            {
                Object.DestroyImmediate(original);
            }
            else
            {
                Object.Destroy(original);
            }
        }

        /// <summary>
        /// 销毁组件的游戏对象
        /// </summary>
        /// <param name="original">原始组件</param>
        /// <param name="immediately">马上的</param>
        public static void DestroyGameObject(this Component original, bool immediately = false)
        {
            if (original == null)
                return;
            if (immediately)
            {
                Object.DestroyImmediate(original.gameObject);
            }
            else
            {
                Object.Destroy(original.gameObject);
            }
        }

        /// <summary>
        /// 设置组件所在游戏物体的激活状态
        /// </summary>
        /// <param name="original"></param>
        /// <param name="isActive"></param>
        public static void SetActive(this Component original, bool isActive)
        {
            original.gameObject.SetActive(isActive);
        }
    }
}